#include"keyboard.h"
#include"interrupt.h"
#include"io.h"
#include"stdio_kernal.h"
#include"global.h"
#include"circle_buffer.h"

circle_buffer kb_buffer;

static void intr_keyboard(void){
	uint16_t scan_code=0;
	uint16_t m_code=0;
	uint8_t idx;
	bool is_make_code=false;
	static bool extend=false;
	static bool shift_on=false;
	static bool ctrl_on=false;
	static bool alt_on=false;
	uint8_t key_char;

	scan_code=inb(KB_BUF_PORT);
	//printk("s--%x\n",scan_code);
	if(scan_code==0xe0){
		extend=true;
		return;
	}
	
	if(extend){
		scan_code |= 0xe000;
		extend=false;
	}

	is_make_code=(scan_code & 0x80)==0;
	if(is_make_code){
		//make code process
		if(scan_code==shift_l_make || scan_code==shift_r_make){
			shift_on=true;
			return;
		}else if(scan_code==alt_l_make || scan_code==alt_r_make){
			alt_on=true;
			return;
		}else if(scan_code==ctl_l_make || scan_code==ctl_r_make){
			ctrl_on=true;
			return;
		}
		idx=scan_code;
		key_char=keymap[idx][shift_on];
		if(key_char){
			if(ctrl_on && (key_char=='l' || key_char=='u')){
				//change <ctrl>+l <ctrl>+u to ctrl code
				key_char-='a';	
			}
			//put visible char to keyboard circle buffer
			put(&kb_buffer,key_char);
		}
	}else{
		//break code process
		m_code=scan_code & 0xff7f;
		if(m_code==shift_l_make || m_code==shift_r_make){
			shift_on=false;
		}else if(m_code==alt_l_make || m_code==alt_r_make){
			alt_on=false;
		}else if(m_code==ctl_l_make || m_code==ctl_r_make){
			ctrl_on=false;
		}
	}
}

int32_t keyboard_read(void *buffer,uint32_t cnt){
	uint32_t read_bytes=0;
	char* key_data=(void*)buffer;
	while(read_bytes<cnt){
		key_data[read_bytes]=get(&kb_buffer);
		read_bytes++;
	}
	return (int32_t)read_bytes;
}

void init_keyboard(void){
	register_intr_handler(KB_IRQ,(intr_handler)intr_keyboard);
	circle_buffer_init(&kb_buffer,512);
	printk("keyboard init done\n");
}
